package com.zc.angelica.config.sucurity;


import com.zc.angelica.config.sucurity.filter.JwtAuthenticationTokenFilter;
import com.zc.angelica.config.sucurity.filter.JwtLoginFilter;
import com.zc.angelica.config.sucurity.handler.*;
import com.zc.angelica.service.AccountService;
import com.zc.angelica.service.LastingLoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {



    @Autowired
    private LoginErrorHanler loginErrorHanler;


    @Autowired
    private MyAccessDeniedHandler myAccessDeniedHandler;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private MyPermissionEvaluator myPermissionEvaluator;

    @Autowired
    private UserService userService;

    @Autowired
    private AccountService accountService;

    @Value("${validateCode.enabled}")
    private Boolean enabledVerifyCode;

    @Value("${jwt.lasting-code}")
    private String lastingCode;

    @Autowired
    private LastingLoginService lastingLoginService;

    @Autowired
    private MyLogoutSuccessHandler myLogoutSuccessHandler;

    @Autowired
    private MyAuthenticationProvider myAuthenticationProvider;



    /**
     * 登录持久化
     */
    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setDataSource(dataSource);
        // 如果token表不存在，使用下面语句可以初始化该表；若存在，请注释掉这条语句，否则会报错。
//        tokenRepository.setCreateTableOnStartup(true);
        return tokenRepository;
    }


    /**
     * 权限认证
     */
    @Bean
    public DefaultWebSecurityExpressionHandler myWebSecurityExpressionHandler() {
        DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();
        handler.setPermissionEvaluator(myPermissionEvaluator);
        return handler;
    }

    // 自定义的Jwt Token过滤器
    @Bean
    public JwtAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception {
        return new JwtAuthenticationTokenFilter(super.authenticationManager(),loginErrorHanler,lastingLoginService,userService);
    }

//    @Bean
//    JwtLoginFilter loginFilter() throws Exception {
//        JwtLoginFilter jwtLoginFilter = new JwtLoginFilter(authenticationManager());
////        jwtLoginFilter.setAuthenticationManager(super.authenticationManager());
//        jwtLoginFilter.setAuthenticationSuccessHandler(loginSuccessHandler);
//        jwtLoginFilter.setAuthenticationFailureHandler(loginErrorHanler);
//        return jwtLoginFilter;
//    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.httpBasic()
                .and()
                .authorizeRequests()
                .antMatchers("/getCode").permitAll()
                .anyRequest().authenticated()//所有请求都需要认证
                .and()
                .formLogin() //登录表单
                .loginPage("/login")//登录页面url
                .loginProcessingUrl("/login")//登录验证url
                .defaultSuccessUrl("/index")//成功登录跳转
                .permitAll()//登录成功后有权限访问所有页面
                .and()
                .logout()
                .logoutUrl("/logout")
                .logoutSuccessHandler(myLogoutSuccessHandler)
                .and()
                .rememberMe()
                .tokenRepository(persistentTokenRepository())
                .tokenValiditySeconds(60)
                // 开启跨域
                .and()
                .cors()
        ;
        //关闭csrf跨域攻击防御
        http.csrf().disable();
        http.addFilterAt(new JwtLoginFilter(myAuthenticationProvider), UsernamePasswordAuthenticationFilter.class);
        http.exceptionHandling()
                .accessDeniedHandler(myAccessDeniedHandler);

        //配置自己的jwt验证过滤器
        http.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
        http.sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    }


    /**
     * BCrypt加密
     *
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 解决 AuthenticationManager 无法注入的问题
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }




}
